1 using UnityEngine;
2 using
Hashtable = ExitGames.Client.Photon.Hashtable;
3
4 [RequireComponent(
typeof(PhotonView))]
5 public
class CubeInter : Photon.MonoBehaviour
6 {
7     
8     
//
9     
// NOTE: Network interpolation is affected by the network sendRate.
10     
// By default this is 10 times/second for OnSerialize. (See PhotonNetwork.sendIntervalOnSerialize)
11     
// Raise the sendrate if you want to lower the interpolationBackTime.
12     
//
13     
14     
public double interpolationBackTime = 0.15;
15
16     
internal struct State
17     {
18         
internal double timestamp;
19         
internal Vector3 pos;
20         
internal Quaternion rot;
21     }
22
23     
// We store twenty states with "playback" information
24     State[] m_BufferedState =
new State[20];
25     
// Keep track of what slots are used
26     
int m_TimestampCount;
27
28     
void Awake()
29     {
30         
if (photonView.isMine)
31             
this.enabled = false;//Only enable inter/extrapol for remote players
32     }
33
34     
void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
35     {
36         
// Always send transform (depending on reliability of the network view)
37         
if (stream.isWriting)
38         {
39             Vector3 pos = transform.localPosition;
40             Quaternion rot = transform.localRotation;
41             stream.Serialize(
ref pos);
42             stream.Serialize(
ref rot);
43         }
44         
// When receiving, buffer the information
45         
else
46         {
47             
// Receive latest state information
48             Vector3 pos = Vector3.zero;
49             Quaternion rot = Quaternion.identity;
50             stream.Serialize(
ref pos);
51             stream.Serialize(
ref rot);
52
53             
// Shift buffer contents, oldest data erased, 18 becomes 19, ... , 0 becomes 1
54             
for (int i = m_BufferedState.Length - 1; i >= 1; i--)
55             {
56                 m_BufferedState[i] = m_BufferedState[i -
1];
57             }
58             
59             
60             
// Save currect received state as 0 in the buffer, safe to overwrite after shifting
61             State state;
62             state.timestamp = info.timestamp;
63             state.pos = pos;
64             state.rot = rot;
65             m_BufferedState[
0] = state;
66
67             
// Increment state count but never exceed buffer size
68             m_TimestampCount = Mathf.Min(m_TimestampCount +
1, m_BufferedState.Length);
69
70             
// Check integrity, lowest numbered state in the buffer is newest and so on
71             
for (int i = 0; i < m_TimestampCount - 1; i++)
72             {
73                 
if (m_BufferedState[i].timestamp < m_BufferedState[i + 1].timestamp)
74                     Debug.Log(
"State inconsistent");
75             }
76         }
77     }
78
79     
// This only runs where the component is enabled, which is only on remote peers (server/clients)
80     
void Update()
81     {
82         
double currentTime = PhotonNetwork.time;
83         
double interpolationTime = currentTime - interpolationBackTime;
84         
// We have a window of interpolationBackTime where we basically play
85         
// By having interpolationBackTime the average ping, you will usually use interpolation.
86         
// And only if no more data arrives we will use extrapolation
87
88         
// Use interpolation
89         
// Check if latest state exceeds interpolation time, if this is the case then
90         
// it is too old and extrapolation should be used
91         
if (m_BufferedState[0].timestamp > interpolationTime)
92         {
93              
for (int i = 0; i < m_TimestampCount; i++)
94             {
95                 
// Find the state which matches the interpolation time (time+0.1) or use last state
96                 
if (m_BufferedState[i].timestamp <= interpolationTime || i == m_TimestampCount - 1)
97                 {
98                     
// The state one slot newer (<100ms) than the best playback state
99                     State rhs = m_BufferedState[Mathf.Max(i -
1, 0)];
100                     
// The best playback state (closest to 100 ms old (default time))
101                     State lhs = m_BufferedState[i];
102
103                     
// Use the time between the two slots to determine if interpolation is necessary
104                     
double length = rhs.timestamp - lhs.timestamp;
105                     
float t = 0.0F;
106                     
// As the time difference gets closer to 100 ms t gets closer to 1 in
107                     
// which case rhs is only used
108                     
if (length > 0.0001)
109                         t = (
float)((interpolationTime - lhs.timestamp) / length);
110
111                     
// if t=0 => lhs is used directly
112                     transform.localPosition = Vector3.Lerp(lhs.pos, rhs.pos, t);
113                     transform.localRotation = Quaternion.Slerp(lhs.rot, rhs.rot, t);
114                     
return;
115                 }
116             }
117         }
118         
// Use extrapolation. Here we do something really simple and just repeat the last
119         
// received state. You can do clever stuff with predicting what should happen.
120         
else
121         {
122             State latest = m_BufferedState[
0];
123
124             transform.localPosition = Vector3.Lerp(transform.localPosition, latest.pos, Time.deltaTime *
20 );
125             transform.localRotation = latest.rot;
126         }
127     }
128 }


NOTE: Network interpolation is affected by the network sendRate.

By default this is 10 timessecond for OnSerialize. (See PhotonNetwork.sendIntervalOnSerialize)

Raise the sendrate if you want to lower the interpolationBackTime.

We store twenty states with "playback" information

Keep track of what slots are used

this.enabled = false;Only enable interextrapol for remote players

Always send transform (depending on reliability of the network view)

When receiving, buffer the information

Receive latest state information

Shift buffer contents, oldest data erased, 18 becomes 19, ... , 0 becomes 1

Save currect received state as 0 in the buffer, safe to overwrite after shifting

Increment state count but never exceed buffer size

Check integrity, lowest numbered state in the buffer is newest and so on

This only runs where the component is enabled, which is only on remote peers (serverclients)

We have a window of interpolationBackTime where we basically play

By having interpolationBackTime the average ping, you will usually use interpolation.

And only if no more data arrives we will use extrapolation

Use interpolation

Check if latest state exceeds interpolation time, if this is the case then

it is too old and extrapolation should be used

Find the state which matches the interpolation time (time+0.1) or use last state

The state one slot newer (<100ms) than the best playback state

The best playback state (closest to 100 ms old (default time))

Use the time between the two slots to determine if interpolation is necessary

As the time difference gets closer to 100 ms t gets closer to 1 in

which case rhs is only used

if t=0 => lhs is used directly

Use extrapolation. Here we do something really simple and just repeat the last

received state. You can do clever stuff with predicting what should happen.




Trò chơi Tic-Tac-Toe, game đánh caro full source code 53.564 lượt xem

Gõ tìm kiếm nhanh...